package com.example.xzs.admin.userlogin.filter;

import com.alibaba.fastjson.JSON;
import com.example.xzs.admin.userlogin.JsoResult.JsonResult;
import com.example.xzs.admin.userlogin.dao.repository.IUserRepository;
import com.example.xzs.admin.userlogin.enumerator.ServiceCode;
import com.example.xzs.admin.userlogin.pojo.vo.PartyMessage;
import com.example.xzs.admin.userlogin.pojo.vo.UserLoginInfoVo;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;

@Component
@Slf4j
public class Jwt extends OncePerRequestFilter {
    @Autowired
    private IUserRepository iUserRepository;
    public Jwt() {
        log.debug("创建过滤器对象：JWT");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.debug("JWT类开始运作");
        String jwt=request.getHeader("Authorization");
        log.debug("获取客户端携带的JWT：{}", jwt);

        if(!StringUtils.hasText(jwt)){
            filterChain.doFilter(request,response);
            return;
        }
        response.setContentType("application/json; charset=utf-8");
         //开始解析
        String  secretKey="k4^&32flj5Ss(Jf&*(5%DK3da"; //私有钥匙要与生成jWT相同
        Claims claims=null;

        try {
            claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(jwt)
                    .getBody();
        }catch (SignatureException e) {
            String message = "非法访问！";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE, message);
            String jsonResultString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter = response.getWriter();
            printWriter.println(jsonResultString);
            printWriter.close();
            return;
        } catch (MalformedJwtException e) {
            String message = "非法访问！";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_MALFORMED, message);
            String jsonResultString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter = response.getWriter();
            printWriter.println(jsonResultString);
            printWriter.close();
            return;
        } catch (ExpiredJwtException e) {
            String message = "您的登录信息已过期，请重新登录！";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_EXPIRED, message);
            String jsonResultString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter = response.getWriter();
            printWriter.println(jsonResultString);
            printWriter.close();
            return;
        } catch (Throwable e) {
            log.debug("全局异常处理器开始处理Throwable");
            log.debug("异常跟踪信息如下：", e);
            String message = "服务器忙，请稍后再试！【同学们，看到这句时，你应该检查服务器端的控制台，并在JwtAuthorizationFilter中补充catch代码块进行处理】";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNKNOWN, message);
            String jsonResultString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter = response.getWriter();
            printWriter.println(jsonResultString);
            printWriter.close();
            return;
        }

/*------------------------------------------------------------------------------*/

        Long id=claims.get("id",Long.class);
        String username=claims.get("username",String.class);
        String admin=claims.get("admin",String.class);
        String jwtRemoteAddr = claims.get("remoteAddr", String.class);
        String jwtUserAgent = claims.get("userAgent", String.class);

        log.debug("id = {}", id);
        log.debug("username = {}", username);
        log.debug("admin = {}", admin);
        log.debug("remoteAddr = {}", jwtRemoteAddr);
        log.debug("userAgent = {}", jwtUserAgent);


        // 检查是否盗用JWT：IP地址和浏览器信息均不匹配
        String currentRemoteAddr = request.getRemoteAddr();
        String currentUserAgent = request.getHeader("User-Agent");
        if (!currentRemoteAddr.equals(jwtRemoteAddr)
                && !currentUserAgent.equals(jwtUserAgent)) {
            log.debug("本次请求疑似盗用JWT的请求，IP地址：{}，浏览器信息：{}", currentRemoteAddr, currentUserAgent);
            filterChain.doFilter(request, response);
            return;
        }

        UserLoginInfoVo userLoginInfoVo=iUserRepository.selectUser(username);

        if(userLoginInfoVo.getEnable()!=1){
            String message="您的账号已经被禁用!";
            JsonResult jsonResult=JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
            String jsonResultString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(jsonResultString);
            printWriter.close();
            return;
        }

        PartyMessage partyMessage=new PartyMessage();
        partyMessage.setId(id);
        partyMessage.setUsername(username);



        Object principal=username;
        Collection<GrantedAuthority> authorities=new ArrayList<>();
        GrantedAuthority authority=new SimpleGrantedAuthority(admin);
        authorities.add(authority);
        Authentication authentication=new UsernamePasswordAuthenticationToken(
                principal,null,authorities
        );
        SecurityContext securityContext= SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);

        filterChain.doFilter(request,response);
    }
}
